package com.cskaoyan.catmall.service.Impl;

import com.cskaoyan.catmall.bean.CouponData;
import com.cskaoyan.catmall.bean.UserCouponData;
import com.cskaoyan.catmall.bean.UserOrderDetail;
import com.cskaoyan.catmall.dao.WxCouponMapper;
import com.cskaoyan.catmall.dao.WxUserMapper;
import com.cskaoyan.catmall.model.bo.BaseParamBo;
import com.cskaoyan.catmall.model.bo.WxCouponMyListBo;
import com.cskaoyan.catmall.model.vo.WxCouponListVo;
import com.cskaoyan.catmall.model.vo.WxCouponMyListVo;
import com.cskaoyan.catmall.model.vo.WxCouponSelectListVo;
import com.cskaoyan.catmall.service.WxCouponService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.*;

/**
 * 创建日期: 2022-01-10-17-12
 * author : WQW
 * description: 用户优惠卷相关的增删改查
 */

@Service
public class WxCouponServiceImpl implements WxCouponService {

    @Autowired
    WxCouponMapper wxCouponMapper;
    @Autowired
    WxUserMapper wxUserMapper;


    /**
     * @param
     * @param couponMyListBo
     * @param username
     * @return com.cskaoyan.catmall.model.vo.WxCouponMyListVo
     * @description 获取指定用户优惠卷信息，并分页
     * @author WQW
     * @date 2022/1/10 17:26
     */
    @Override
    public WxCouponMyListVo getUserCoupon(WxCouponMyListBo wxCouponMyListBo, Integer userId) {
        Integer page = wxCouponMyListBo.getPage();// 页码
        Integer limit = wxCouponMyListBo.getLimit();// 每页数据量
        PageHelper.startPage(page, limit);
        List<WxCouponMyListVo.ListDTO> wxCouponMyListVos = wxCouponMapper.selectUserCoupon(wxCouponMyListBo.getStatus(), userId);
        PageInfo<WxCouponMyListVo.ListDTO> wxCouponMyListVoPageInfo = new PageInfo<>(wxCouponMyListVos);
        int pages = wxCouponMyListVoPageInfo.getPages();
        long total = wxCouponMyListVoPageInfo.getTotal();
        return new WxCouponMyListVo(total, pages, limit, page, wxCouponMyListVos);
    }


    /**
     * @param
     * @param baseParamBo
     * @return com.cskaoyan.catmall.model.vo.WxCouponListVo
     * @description 查询所有用户可领取的优惠卷信息
     * @author WQW
     * @date 2022/1/10 21:45
     */
    @Override
    public WxCouponListVo getAllCoupon(BaseParamBo baseParamBo) {
        Integer page = baseParamBo.getPage();// 页码
        Integer limit = baseParamBo.getLimit();// 每页的数量
        PageHelper.startPage(page, limit);
        List<WxCouponListVo.ListDTO> wxCouponList = wxCouponMapper.selectAllCoupon();
        PageInfo<WxCouponListVo.ListDTO> listDTOPageInfo = new PageInfo<>(wxCouponList);
        int pages = listDTOPageInfo.getPages();
        long total = listDTOPageInfo.getTotal();
        return new WxCouponListVo(total, pages, limit, page, wxCouponList);
    }


    /**
     * @param
     * @param couponId
     * @return int
     * @description
     * @author WQW
     * @date 2022/1/10 21:47
     */
    @Transactional
    @Override
    public int userGetCoupon(Integer couponId, Integer userId) {
        // 首先根据优惠卷id，查看领取数量限制,有效时间限制，有效天数，优惠卷有效期
        CouponData couponData = wxCouponMapper.selectCouponById(couponId);
        // 然后查询所有用户已经领取的该种优惠卷的数量
        int usagesQuantity = wxCouponMapper.selectCountCouponByCouponId(couponId);
        // 计算该种优惠卷剩余数量,如果剩余数量小于等于0，则返回优惠卷已经领取完102
        Integer couponBalance = couponData.getTotal() - usagesQuantity;
        if (couponBalance <= 0) {
            return 102;
        }
        // 获取该种优惠卷每个用户限制领取的数量limit
        // 如果limit等于0，说明该种优惠卷没有数量限制，否则计算优惠卷剩余数量
        // 如果limit不等于0，则计算查询该用户已经领取过该种优惠卷的数量
        Short limit = couponData.getLimit();
        if (limit != 0) {
            int usageQuantity = wxCouponMapper.selectCountCountByUserIdAndCouponId(couponId, userId); // 查询该用户领取过该优惠卷的数量
            // 如果该用户领取过该优惠卷的数量大于等于该种优惠卷每个用户限制领取数量，则返回优惠卷已经领取过101
            if (usageQuantity >= limit) {
                return 101;
            }
        }
        // 否则返回领取成功，同时将该领取信息加入用户优惠卷表
        // 首先判断该种类型优惠卷的有效时间限制
        // 如果有效时间限制为0，则基于领取时间的有效天数days
        // 如果有效时间限制为1，则使用优惠卷的有效期
        if (couponData.getTimeType() == 0) {
            Instant nowTime = Instant.now();// 获取当前时间
            Instant plusTime = nowTime.plus(Duration.ofDays(couponData.getDays()));// 计算优惠卷过期时间
            // 将时间转换成指定格式
            String nowTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.from(nowTime));
            String plusTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.from(plusTime));
            couponData.setStartTime(nowTimeFormat);
            couponData.setEndTime(plusTimeFormat);
            wxCouponMapper.insertCouponUser(couponData, userId);
        } else {
            wxCouponMapper.insertCouponUser(couponData, userId);
        }
        return 200;
    }


    /**
     * @description 兑换优惠卷
     * @author WQW
     * @date 2022/1/12 16:35
     * @param
     * @param code
     * @param userId
     * @return int
     */
    @Override
    public int exchangeCoupon(String code, Integer userId) {
        // 首先根据code查询是否存在正常状态下的该优惠卷信息，如果没有则则返回优惠卷兑换码不正确103
        // 如果存在则返回该优惠卷的相关信息
        CouponData couponData = wxCouponMapper.selectCouponByCode(code);
        if (couponData == null) {
            return 103;
        }
        // 如果该兑换码对应的优惠卷存在，但是已过期，则返回兑换码过期104
        if (couponData.getStatus()==1){
            return 104;
        }
        // 然后查询该种优惠卷已经被领取的数量，并计算优惠卷的剩余数量
        int usagesQuantity = wxCouponMapper.selectCountCouponByCouponId(couponData.getId());
        // 如果剩余数量小于等于0，则返回优惠卷已经兑换完102
        Integer couponBalance = couponData.getTotal() - usagesQuantity;
        if (couponBalance <= 0) {
            return 102;
        }
        // 获取该种优惠卷每个用户限制领取的数量limit
        // 如果limit等于0，说明该种优惠卷没有数量限制，否则计算优惠卷剩余数量
        // 如果limit不等于0，则计算查询该用户已经领取过该种优惠卷的数量
        Short limit = couponData.getLimit();
        if (limit != 0) {
            int usageQuantity = wxCouponMapper.selectCountCountByUserIdAndCouponId(couponData.getId(), userId); // 查询该用户领取过该优惠卷的数量
            // 如果该用户领取过该优惠卷的数量大于等于该种优惠卷每个用户限制领取数量，则返回优惠卷已经领取过101
            if (usageQuantity >= limit) {
                return 101;
            }
        }
        // 否则返回领取成功，同时将该领取信息加入用户优惠卷表
        // 首先判断该种类型优惠卷的有效时间限制
        // 如果有效时间限制为0，则基于领取时间的有效天数days
        // 如果有效时间限制为1，则使用优惠卷的有效期
        if (couponData.getTimeType() == 0) {
            Instant nowTime = Instant.now();// 获取当前时间
            Instant plusTime = nowTime.plus(Duration.ofDays(couponData.getDays()));// 计算优惠卷过期时间
            // 将时间转换成指定格式
            String nowTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.from(nowTime));
            String plusTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.from(plusTime));
            couponData.setStartTime(nowTimeFormat);
            couponData.setEndTime(plusTimeFormat);
            wxCouponMapper.insertCouponUser(couponData, userId);
        } else {
            wxCouponMapper.insertCouponUser(couponData, userId);
        }
        return 200;
    }

    /**
     * @param
     * @param userId
     * @return com.cskaoyan.catmall.model.vo.WxCouponSelectListVo
     * @description 获取用户可用的优惠卷信息
     * @author WQW
     * @date 2022/1/11 22:45
     */
    @Override
    public WxCouponSelectListVo getUserAvailableCoupon(Integer userId) {
        // 首先根据用户id查询该用户所拥有的所有正常状态下的优惠卷相关信息
        List<UserCouponData> userCouponDataList = wxCouponMapper.selectUserCouponList(userId);
        // 然后计算用户选中的下单商品信息，并计算出下单总额
        List<UserOrderDetail> userOrderDetails = wxCouponMapper.selectUserCart(userId);
        Double amount = 0.0;// 下单总额
        for (UserOrderDetail userOrderDetail : userOrderDetails) {
            amount += userOrderDetail.getNumber() * userOrderDetail.getPrice();
        }
        // 然后根据下单总额计算出通用优惠卷中可使用的优惠卷,将可用状态设置为true
        for (UserCouponData userCouponData : userCouponDataList) {
            if (userCouponData.getGoodsType() == 0 && userCouponData.getMin() <= amount) {
                userCouponData.setAvailable(true);
            }
        }
        // 然后根据商品信息计算出同类商品总额，并找出指定商品优惠卷中可以使用的优惠卷信息，并将该优惠卷状态设置为true
        HashMap<Integer, Double> userGoodsMap = new HashMap<>();
        for (UserOrderDetail userOrderDetail : userOrderDetails) {
            if (userGoodsMap.containsKey(userOrderDetail.getGoodsId())) {
                userGoodsMap.replace(userOrderDetail.getGoodsId(), userGoodsMap.get(userOrderDetail.getGoodsId()) + (userOrderDetail.getPrice() * userOrderDetail.getNumber()));
            } else {
                userGoodsMap.put(userOrderDetail.getGoodsId(), userOrderDetail.getPrice() * userOrderDetail.getNumber());
            }
        }

        // 遍历用户下单商品map
        Iterator<Map.Entry<Integer, Double>> iterator = userGoodsMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, Double> next = iterator.next();
            // 遍历用户优惠卷集合，找出所有goodsType为1的集合
            for (UserCouponData userCouponData : userCouponDataList) {
                if (userCouponData.getGoodsType() == 1 && userCouponData.getGoodsValues() != null && userCouponData.getGoodsValues().length != 0) {
                    List<Integer> integerList = Arrays.asList(userCouponData.getGoodsValues());// 将该优惠卷限制商品id数组转为list
                    if (integerList.contains(next.getKey())) {
                        if (userCouponData.getMin()<next.getValue()){
                            userCouponData.setAvailable(true);
                        }
                    }
                }
            }
        }


        // 然后根据商品信息计算出同类目下商品总额，并找出指定类目优惠卷中可以使用的优惠卷信息，并将该优惠卷信息设置为true
        HashMap<Integer, Double> userCategoryMap = new HashMap<>();
        for (UserOrderDetail userOrderDetail : userOrderDetails) {
            if (userCategoryMap.containsKey(userOrderDetail.getCategoryId())) {
                userGoodsMap.replace(userOrderDetail.getCategoryId(), userGoodsMap.get(userOrderDetail.getCategoryId()) + (userOrderDetail.getPrice() * userOrderDetail.getNumber()));
            } else {
                userGoodsMap.put(userOrderDetail.getCategoryId(), userOrderDetail.getPrice() * userOrderDetail.getNumber());
            }
        }

        // 遍历用户下单类目map
        Iterator<Map.Entry<Integer, Double>> iterators = userCategoryMap.entrySet().iterator();
        while (iterators.hasNext()) {
            Map.Entry<Integer, Double> next = iterators.next();
            // 遍历用户优惠卷集合，找出所有goodsType为1的集合
            for (UserCouponData userCouponData : userCouponDataList) {
                if (userCouponData.getGoodsType() == 2 && userCouponData.getGoodsValues() != null && userCouponData.getGoodsValues().length != 0) {
                    List<Integer> integerList = Arrays.asList(userCouponData.getGoodsValues());// 将该优惠卷限制商品id数组转为list
                    if (integerList.contains(next.getKey())) {
                        if (userCouponData.getMin()<next.getValue()){
                            userCouponData.setAvailable(true);
                        }
                    }
                }
            }
        }
        ArrayList<WxCouponSelectListVo.ListDTO> listDTOS = new ArrayList<>();
        for (UserCouponData userCouponData : userCouponDataList) {
            listDTOS.add(new WxCouponSelectListVo.ListDTO(userCouponData.getId(),userCouponData.getCid(),userCouponData.getName(),userCouponData.getDesc(),userCouponData.getTag(),userCouponData.getMin(),userCouponData.getDiscount(),userCouponData.getStartTime(),userCouponData.getEndTime(),userCouponData.getAvailable()));
        }
        return new WxCouponSelectListVo(userCouponDataList.size(),1,userCouponDataList.size(),1, listDTOS);
    }
}
